home *** CD-ROM | disk | FTP | other *** search
/ United Public Domain Gold 2 / United Public Domain Gold 2.iso / utilities / pu062.dms / pu062.adf / Dissolve / dissolve.c < prev    next >
C/C++ Source or Header  |  1987-06-27  |  18KB  |  708 lines

  1. /* :bk=0 */
  2.  
  3. /****************************************************************************/
  4. /*                                                                            */
  5. /*                        Dissolve.c                                            */
  6. /*                                                                            */
  7. /* Author: Lee M. Robertson                                                    */
  8. /*    Based on an article in the Nov '86 Doctor Dobb's Journal                 */
  9. /*    by Mike Morton                                                            */
  10. /****************************************************************************/
  11.  
  12. #include "fcntl.h"
  13. #include "exec/types.h"
  14. #include "exec/memory.h"
  15. #include "graphics/copper.h"
  16. #include "graphics/gfx.h"
  17. #include "graphics/view.h"
  18. #include "graphics/rastport.h"
  19. #include "hardware/blit.h"
  20. #include "hardware/custom.h"
  21. #include "intuition/intuition.h"
  22.  
  23. /*---------------------------------------------------------------------------
  24.  * following are definitions from the IFF specification
  25.  *-------------------------------------------------------------------------*/
  26. struct BitMapHeader
  27. {
  28.     UWORD w, h;
  29.     WORD  x, y;
  30.     UBYTE nPlanes;
  31.     UBYTE masking;
  32.     UBYTE compression;
  33.     UBYTE pad1;
  34.     UWORD transparentColor;
  35.     UBYTE xAspect, yAspect;
  36.     WORD  pageWidth, pageHeight;
  37. };
  38.  
  39. typedef unsigned long ID;
  40.  
  41. struct Chunk
  42. {
  43.     ID        ckID;
  44.     long    ckSize;
  45. };
  46.  
  47. struct ColorRegister
  48. {
  49.     UBYTE red, green, blue;
  50. };
  51.  
  52. #define CSIZE sizeof(chunk)
  53. #define BMHDSIZE sizeof( struct BitMapHeader)
  54.  
  55. #define mskNone 0
  56. #define mskHasMask 1
  57. #define mskHasTransparentColor 2
  58. #define mskLasso 3
  59. #define cmpNone 0                    /* file is not compressed */
  60. #define cmpByteRun1 1                /* file is Run Length Encoded */
  61.  
  62. #define MakeID(a,b,c,d) ( (long)(a)<<24 | (long)(b)<<16 | (long)(c)<<8 | (d) )
  63. #define FORM MakeID('F','O','R','M')
  64. #define ILBM MakeID('I','L','B','M')
  65. #define LIST MakeID('L','I','S','T')
  66. #define BODY MakeID('B','O','D','Y')
  67. #define BMHD MakeID('B','M','H','D')
  68. #define CMAP MakeID('C','M','A','P')
  69.  
  70. /*---------------------------------------------------------------------------
  71.  * Picture structure - this contains all the revalent data for a picture file
  72.  *-------------------------------------------------------------------------*/
  73. /* define for the # of bytes in the color register map */
  74. #define CMSIZE 3*32
  75.  
  76. struct picture
  77. {
  78.     int numcolors;                    /* # of valid colors */
  79.     int fd;                            /* the file # for this file */
  80.     struct BitMap *bm;                /* a bitmap to store the picture */
  81.     long bodysize;                    /* # of bytes in the body data */
  82.     struct BitMapHeader bmhd;
  83.     UBYTE cmap[CMSIZE];                /* the color values for this picture */
  84.     /* don't use the ColorRegister structure if using Aztec 'C' */
  85. };
  86.  
  87. struct picture pic1,pic2;            /* some picture sturcts */
  88. struct BitMap BitMap;                /* bitmap to read pictue into */
  89. struct GfxBase *GfxBase;
  90. struct IntuitionBase *IntuitionBase;
  91. struct Window *Window;
  92. struct Screen *Screen;
  93. struct ViewPort *vp,*ViewPortAddress();
  94.  
  95. void *OpenLibrary();
  96. void *GetMsg();
  97. void *AllocMem();
  98. void *OpenScreen();
  99. void *OpenWindow();
  100.  
  101. #define INTUITION_REV 29L
  102. #define GRAPHICS_REV 29L
  103.  
  104. struct NewWindow NewWindow = 
  105. {
  106.     0,                            /* left edge */
  107.     0,                            /* top edge  */
  108.     320,                        /* width     */
  109.     200,                        /* heigth    */
  110.     0,1,                        /* pen's     */
  111.  
  112.     /* IDCmpFlags */
  113.     RAWKEY | MOUSEBUTTONS | CLOSEWINDOW,
  114.  
  115.     /* flags */
  116.     RMBTRAP | WINDOWCLOSE | BACKDROP | NOCAREREFRESH | BORDERLESS | ACTIVATE,
  117.  
  118.     0,                            /* gadget list */
  119.     0,                            /* check mark */
  120.     0,                            /* title pointer */
  121.     0,                            /* screen pointer */
  122.     0,                            /* bitmap pointer */
  123.     0,0,                        /* minimum sizes */
  124.     0,0,                        /* maximum sizes */
  125.     CUSTOMSCREEN,
  126. };
  127.  
  128. struct NewScreen NewScreen =
  129. {
  130.     0,                            /* left edge */
  131.     0,                            /* top edge  */
  132.     320,                        /* width     */
  133.     200,                        /* heigth    */
  134.     5,                            /* depth     */
  135.     0,1,                        /* pen's     */
  136.     0,                            /* view modes */
  137.     CUSTOMSCREEN,                /* type      */
  138.     0,                            /* font      */
  139.     (UBYTE *)"Screen",            /* title     */
  140.     0,                            /* gagets    */
  141.     0,                            /* bitmap    */
  142. };
  143.  
  144.  
  145. /*---------------------------------------------------------------------------
  146.  * main()
  147.  *-------------------------------------------------------------------------*/
  148. main(argc,argv)
  149. int argc;
  150. char *argv[];
  151. {
  152.     char *open_pic();
  153.     char *rd_bmap();
  154.     char *errmsg;
  155.     int speed;
  156.     register int i;
  157.     register long psize;        /* the plane size in bytes */
  158.     register char *arg;
  159.     register char *filename;
  160.  
  161.     if(argc < 2)
  162.     {
  163.         printf("Usage: Dissolve filename [ -# ]\n");
  164.         exit(0);
  165.     }
  166.  
  167.     for( i=1; i < argc; i++ )
  168.     {
  169.         argv++;
  170.         arg = *argv;
  171.         if( *arg == '-' )
  172.             speed = atoi( arg + 1 );
  173.         else
  174.             filename = arg;
  175.     }
  176.  
  177.     if( speed < 100 )
  178.         speed = 1000;
  179.  
  180.     open_libs();            /* open the libraries */
  181.  
  182.     /* open the picture files */
  183.     if( errmsg = open_pic( filename, &pic1 ))
  184.     {
  185.         printf("%s: %s\n",errmsg,filename );
  186.         end( 10 );
  187.     }
  188.     /* setup the temp bitmap for the data */
  189.     BitMap.BytesPerRow = (pic1.bmhd.w >> 4) << 1;
  190.     BitMap.Rows = pic1.bmhd.h;
  191.     BitMap.Depth = pic1.bmhd.nPlanes;
  192.  
  193.     psize = BitMap.BytesPerRow * BitMap.Rows;    /* calculate the plane size */
  194.  
  195.     if( psize == 0 || pic1.bmhd.nPlanes > 6 )
  196.     {
  197.         printf("Ivalid parameters: %s\n",filename);
  198.         end( 10 );
  199.     }
  200.  
  201.     NewScreen.Width = pic1.bmhd.w;
  202.     NewScreen.Height = pic1.bmhd.h;
  203.     NewScreen.Depth = pic1.bmhd.nPlanes;
  204.  
  205.     /* set bits for display modes */
  206.     if( NewScreen.Depth == 6 && NewScreen.Width <= 320 )
  207.         NewScreen.ViewModes |= HAM;
  208.  
  209.     if( NewScreen.Height > 200 )
  210.         NewScreen.ViewModes |= LACE;
  211.  
  212.     if( NewScreen.Width > 320 )
  213.         NewScreen.ViewModes |= HIRES;
  214.  
  215.     Screen = OpenScreen( &NewScreen);
  216.     if( Screen == 0 )
  217.     {
  218.         printf("Can't open Screen\n");
  219.         end(10);
  220.     }
  221.  
  222.     NewWindow.Screen = Screen;
  223.     NewWindow.Width = pic1.bmhd.w;
  224.     NewWindow.Height = pic1.bmhd.h;
  225.     Window = OpenWindow( &NewWindow );
  226.     if( Window == 0 )
  227.     {
  228.         printf("Can't open Window\n");
  229.         end( 10 );
  230.     }
  231.     ShowTitle( Screen, 0L );            /* hide the screen title */
  232.     vp = ViewPortAddress( Window );        /* get the windows viewport */
  233.  
  234.     SetRast( Window->RPort, 0L );        /* clear the screen */
  235.     setcolors( vp, &pic1.cmap[0], pic1.numcolors );
  236.  
  237.     errmsg = "No memory for BitMap";
  238.     /* Allocate memory for plane data */
  239.     for( i=0; i<BitMap.Depth; i++ )
  240.     {
  241.         if( (BitMap.Planes[i] = AllocMem( psize, MEMF_CHIP)) == 0 )
  242.             goto nomem;
  243.     }
  244.  
  245.     /* Now read the picture into the temp bitmap */
  246.     errmsg = rd_bmap( &BitMap, &pic1 );
  247.  
  248.     if( errmsg == 0 )
  249.     {
  250.         if( (dissolve( &BitMap, Window->RPort->BitMap, speed) ) == 0 )
  251.         {
  252.             while( get_message() == 0 )
  253.                 WaitPort( Window->UserPort);
  254.         }
  255.     }
  256.  
  257. nomem:
  258.     for( i=0; i<8; i++)
  259.     {
  260.         if( BitMap.Planes[i] )
  261.             FreeMem( BitMap.Planes[i],psize );
  262.     }
  263.     if( errmsg )
  264.         printf("%s: %s\n",errmsg,filename);
  265.     end( 0 );
  266.  
  267. }
  268.  
  269. /*---------------------------------------------------------------------------
  270.  * open_pic() -- open a picture file and initialize the picture data struct
  271.  *-------------------------------------------------------------------------*/
  272. char * open_pic( filename, pic )
  273. char *filename;                        /* the picture file name */
  274. register struct picture *pic;        /* the picture data */
  275. {
  276.     register int fd;                /* the picture file descriptor */
  277.     struct Chunk chunk;                /* temp for read data */
  278.     register int cmsize;
  279.  
  280.     fd = open( filename, O_RDONLY);               /* open the file */
  281.     if( fd == -1)
  282.         return "Can't open";
  283.  
  284.     if( read(fd, &chunk, CSIZE) != CSIZE )
  285.         goto readerr;
  286.  
  287.     if( chunk.ckID != FORM)
  288.         return "Not a picture file";
  289.  
  290.     /* check for ILBM file */
  291.     if( read(fd, &chunk, sizeof(long) ) != sizeof(long) )
  292.         goto readerr;
  293.     if( chunk.ckID != ILBM )
  294.         return "Not an ILBM file";
  295.  
  296.     if( read(fd, &chunk, CSIZE) != CSIZE )
  297.         goto readerr;
  298.     
  299.     if( chunk.ckID != BMHD)
  300.         return "bit map header expected";
  301.  
  302.     if( chunk.ckSize != BMHDSIZE )
  303.         return "Incorrect BMHD size";
  304.  
  305.     /* read the BMHD data */
  306.     if( read( fd, &pic->bmhd, BMHDSIZE ) != BMHDSIZE )
  307.         goto readerr;
  308.  
  309.     pic->numcolors = 1;            /* set default color map */
  310.  
  311.     /* read chunks untill body is found */
  312.     while( read(fd, &chunk, CSIZE) == CSIZE )
  313.     {
  314.  
  315.         if( chunk.ckID == CMAP)
  316.         {
  317.             /* read the color map */
  318.  
  319.             /* get size of the color map */
  320.             if( chunk.ckSize > CMSIZE )
  321.                 cmsize = CMSIZE;
  322.             else
  323.                 cmsize = chunk.ckSize;
  324.  
  325.             if( read(fd, &pic->cmap[0], cmsize ) != cmsize )
  326.                 goto readerr;
  327.             pic->numcolors = cmsize / 3;        /* save # of colors in picture */
  328.  
  329.             chunk.ckSize++;
  330.             chunk.ckSize &= ~1;
  331.  
  332.             if( chunk.ckSize -= cmsize )
  333.                 lseek( fd, chunk.ckSize, 1 );    /* skip rest of colormap */
  334.         }
  335.  
  336.         if( chunk.ckID == BODY )
  337.         {
  338.             pic->bodysize = chunk.ckSize;
  339.             pic->fd = fd;
  340.             return 0;                    /* no errs */
  341.         }
  342.  
  343.         /* else ignore this chunks data */
  344.         lseek(fd,chunk.ckSize,1);
  345.     }
  346.  
  347. readerr:
  348.     return "Read error";
  349. }
  350.  
  351. /*---------------------------------------------------------------------------
  352.  * open_libs() -- open the required libraries
  353.  *-------------------------------------------------------------------------*/
  354. open_libs()
  355. {
  356.     if( !(IntuitionBase = OpenLibrary("intuition.library",INTUITION_REV)) )
  357.     {
  358.         printf("Can't open Intuition library\n");
  359.         exit(5);
  360.     }
  361.  
  362.     if( !(GfxBase = OpenLibrary("graphics.library",GRAPHICS_REV)) )
  363.     {
  364.         printf("Can't open Graphics library\n");
  365.         CloseLibrary(IntuitionBase);
  366.         exit(5);
  367.     }
  368. }
  369.  
  370. /*---------------------------------------------------------------------------
  371.  * end() -- cleanup and exit
  372.  *-------------------------------------------------------------------------*/
  373. end( err )
  374. int err;
  375. {
  376.     /* cleanup stuff */
  377.     if( Window )
  378.         CloseWindow( Window );
  379.     if( Screen )
  380.         CloseScreen( Screen );
  381.     if( GfxBase )
  382.         CloseLibrary(GfxBase);
  383.     if( IntuitionBase )
  384.         CloseLibrary(IntuitionBase);
  385.  
  386.     exit( err );
  387. }
  388.  
  389. /*---------------------------------------------------------------------------
  390.  * setcolors() -- set the color registers
  391.  *-------------------------------------------------------------------------*/
  392. setcolors( vp, creg, numcolors )
  393. struct ViewPort *vp;
  394. register UBYTE *creg;            /* the color values */
  395. int numcolors;                    /* the # of colors to set */
  396. {
  397.     register ULONG r,g,b;        /* the RGB color values (temporaries) */
  398.     register int i;
  399.  
  400.     for(i=0; i<numcolors; i++)
  401.     {
  402.         r = *creg++ >> 4;
  403.         g = *creg++ >> 4;
  404.         b = *creg++ >> 4;
  405.         SetRGB4( vp, (long)i, (long)r, (long)g, (long)b );
  406.     }
  407. }
  408.  
  409. /*---------------------------------------------------------------------------
  410.  *
  411.  *-------------------------------------------------------------------------*/
  412. get_message()
  413. {
  414.     register ULONG class;
  415.     register USHORT code;
  416.     register struct IntuiMessage *Message;
  417.     static int retval = 0;
  418.  
  419.     while( Message = GetMsg(Window->UserPort) )
  420.     {
  421.         class = Message->Class;
  422.         code  = Message->Code;
  423.         ReplyMsg(Message);
  424.  
  425.         /* allow any key press to end program */
  426.         if( class == CLOSEWINDOW || class == RAWKEY )
  427.             retval = 1;
  428.         /* allow user to hold program with right mouse button */
  429.         else if( class == MOUSEBUTTONS && code == MENUDOWN )
  430.             WaitPort( Window->UserPort);
  431.     }
  432.     return retval;
  433. }
  434.  
  435. /*---------------------------------------------------------------------------
  436.  * rd_bmap() -- read a picture into a bitmap
  437.  *        This routine assumes the bitmap is the correct size to recieve
  438.  *        the picture. No error checking is done.
  439.  *-------------------------------------------------------------------------*/
  440. char *rd_bmap( bm, pic)
  441. struct BitMap *bm;
  442. struct picture *pic;
  443. {
  444.     register UBYTE *buffer;        /* the picture file data */
  445.     register UBYTE *data;
  446.     register unsigned int i;
  447.     register unsigned long size;
  448.     register int nplanes;        /* # of data planes */
  449.     UBYTE *planes[8];            /* array of pointers to plane data */
  450.     void *lmalloc();
  451.     char *error;
  452.  
  453.     if( !( buffer = lmalloc( pic->bodysize)) )
  454.         return "No Memory for body buffer";
  455.  
  456.     error = 0;                    /* clear for return */
  457.  
  458.     size = pic->bodysize;
  459.     data = buffer;
  460.  
  461.     /* read the picture data */
  462.     while( size )
  463.     {
  464.         if( size >= 0x10000 )
  465.             i = 0xffff;
  466.         else
  467.             i = size;
  468.         if( read( pic->fd, data, i ) != i )
  469.         {
  470.             error = "Read error";
  471.             goto err;
  472.         }
  473.         data += i;
  474.         size -= i;
  475.     }
  476.  
  477.     /* setup the data to pass to the decode routines */
  478.  
  479.     nplanes = pic->bmhd.nPlanes;
  480.     if( pic->bmhd.masking == mskHasMask )
  481.         nplanes++;                /* add 1 for the mask plane */
  482.  
  483.     for( i=0; i < 8; i++ )
  484.         planes[i] = bm->Planes[i];            /* copy plane pointers */
  485.     
  486.     i = (pic->bmhd.w >> 4) << 1;            /* # of bytes per row */
  487.  
  488.     if( pic->bmhd.compression == cmpNone )
  489.         decode0( planes,buffer,i,pic->bmhd.h,nplanes);
  490.     else if( pic->bmhd.compression == cmpByteRun1 )
  491.         decode1( planes,buffer,i,pic->bmhd.h,nplanes);
  492.     else
  493.         error = "Can't decode";
  494.  
  495. err:
  496.     free( buffer );                /* dealloc the file data buffer */
  497.     return error;
  498. }
  499.  
  500. /*---------------------------------------------------------------------------
  501.  * decode0() -- decodes the body data with no compression
  502.  *-------------------------------------------------------------------------*/
  503. decode0( planes,data,w,h,nplanes)
  504. UBYTE *planes[];
  505. register UBYTE *data;
  506. register int w,h,nplanes;
  507. {
  508.     register UBYTE **pp;            /* pointer to current plane data */
  509.     register int pcnt;            /* plane counter */
  510.  
  511.     for( ; h; h--)                /* for each row */
  512.     {
  513.         for( pcnt = nplanes, pp = planes; pcnt; pcnt--, pp++ )
  514.         {
  515.             if( *pp )        /* don't move the data if no destination plane */
  516.             {
  517.                 movmem( data, *pp, w);
  518.                 *pp += w;
  519.             }
  520.             data += w;
  521.         }
  522.     }
  523. }
  524.  
  525. /*---------------------------------------------------------------------------
  526.  * decode1() -- decodes the body data with ByteRun1 compression
  527.  *        this should really be in assembly
  528.  *-------------------------------------------------------------------------*/
  529. decode1( planes,data,w,h,nplanes)
  530. UBYTE *planes[];
  531. register BYTE *data;
  532. int w,h,nplanes;
  533. {
  534.     register UBYTE **pp;        /* pointer to current plane data */
  535.     register int pcnt;            /* plane counter */
  536.     register int len;
  537.     register int n;
  538.  
  539.     for( ; h; h--)                /* for each row */
  540.     {
  541.         for( pcnt = nplanes, pp = planes; pcnt; pcnt--, pp++ )
  542.         {
  543.             for(n=w; n > 0; n -= len )
  544.             {
  545.                 len = *data++;
  546.                 if( len >= 0 )
  547.                 {
  548.                     len++;
  549.                     if( *pp )        /* move the data if destination plane */
  550.                     {
  551.                         movmem( data, *pp, len);
  552.                         *pp += len;
  553.                     }
  554.                     data += len;
  555.                 }
  556.                 else if( len != -128 )         /* ignore nop's */
  557.                 {
  558.                     len = -len;
  559.                     len++;
  560.                     if( *pp )        /* move the data if destination plane */
  561.                     {
  562.                         setmem( *pp, len, *data );
  563.                         *pp += len;
  564.                     }
  565.                     data++;
  566.                 }
  567.                 else
  568.                     len = 0;        /* if nop */
  569.             }
  570.         }
  571.     }
  572. }
  573.  
  574. /*---------------------------------------------------------------------------
  575.  * some global variables for the dissolve function
  576.  *-------------------------------------------------------------------------*/
  577. unsigned long rand_mask;        /* the mask value for the random # generator */
  578. unsigned long rand_val;            /* the current random # value */
  579. unsigned long rand_tbl[] =        /* the table of random mask values */
  580. {                                /* from Nov '86 DDJ p. 48 */
  581.     0,0,                        /* first 2 values don't work */
  582.     3,6,
  583.     0xc,0x14,
  584.     0x30,0x60,
  585.     0xb8,0x110,
  586.     0x240,0x500,
  587.     0xca0,0x1b00,
  588.     0x3500,0x6000,
  589.     0xb400,0x12000,
  590.     0x20400,0x72000,
  591.     0x90000,0x140000,
  592.     0x300000,0x420000,
  593.     0xd80000,0x1200000,
  594.     0x3880000,0x7200000,
  595.     0x9000000,0x14000000,
  596.     0x32800000,0x48000000,
  597.     0xa3000000                /* for 32 bits wide */
  598. };
  599.  
  600. /*---------------------------------------------------------------------------
  601.  * dissolve() -- dissolve one bitmap into another
  602.  *        this only works for full width bit maps
  603.  *-------------------------------------------------------------------------*/
  604. dissolve( src, dst, speed )
  605. struct BitMap *src,*dst;
  606. int speed;
  607. {
  608.     register UBYTE *mplane;            /* the dissolve mask plane */
  609.     register long psize;                /* the size of a plane */
  610.     register long nbits;                /* # of bits in a plane */
  611.     register int done;
  612.  
  613.     psize = src->BytesPerRow * src->Rows;
  614.  
  615.     if( (mplane = AllocMem( psize, MEMF_CHIP | MEMF_CLEAR) ) == 0 )
  616.         return -1;
  617.  
  618.     nbits = psize << 3;
  619.     nbits--;                /* max bit is 1 less */
  620.  
  621.     /* initialize the random number generator */
  622.     rand_val = 1;
  623.     rand_mask = rand_tbl[ bitwidth(nbits) ];
  624.     mplane[0] |= 1;            /* set the first bit in the mask plane */
  625.  
  626.     done = 0;        /* clear done flag */
  627.     while( done == 0 )
  628.     {
  629.         done = setbits( mplane, nbits, speed );
  630.         BlitBitMapMask( src, dst, mplane );
  631.         if( get_message() )
  632.             break;
  633.     }
  634.  
  635.     FreeMem( mplane, psize );
  636.     return 0;
  637. }
  638.  
  639. /*---------------------------------------------------------------------------
  640.  * setbits() -- set random bits in a plane
  641.  *-------------------------------------------------------------------------*/
  642. setbits( plane, maxbit, numbits )
  643. UBYTE *plane;
  644. unsigned long maxbit;
  645. unsigned int numbits;
  646. {
  647. #asm
  648.     ;register useage: d5 - max bit # to set, d4 - random generator mask
  649.     ; d3 - current random value, d2 - byte offset in array for bit
  650.     ; d2 - bit # to set, d1 - loop counter
  651. regs    reg        d2-d5
  652.  
  653.     movem.l    regs,-(a7)
  654.     move.l    8(a5),a0        ;get base address of array
  655.     move.l    12(a5),d5        ;get maxbit number
  656.     move    16(a5),d1        ;get # of bits to set
  657.     move.l    _rand_mask,d4
  658.     move.l    _rand_val,d3
  659.     move.l    #0,d0            ;clear ret val for not finished
  660.     subq    #1,d1
  661. loop
  662.     lsr.l    #1,d3            ;rand_val >>= 1;
  663.     bhi        ok                ;bif not 0 || no carry
  664. xor
  665.     eor.l    d4,d3            ;rand_val ^= rand_mask;
  666. ok
  667.     cmp.l    d5,d3            ;if( rand_val > maxbit )
  668.     bls        setbit            ;go set the bit if ok
  669.     bra        loop
  670. setloop
  671.     lsr.l    #1,d3            ;do the shift
  672.     bls        xor                ;bif need to do the exculsive or
  673. setbit
  674.     move.l    d3,d2            ;copy to temp reg
  675.     lsr.l    #3,d2            ;make it a byte offset
  676.     bset    d3,0(a0,d2.l)    ;set the bit in the array
  677.     dbne    d1,setloop        ;end if bit is already set || # of bits done
  678.     beq        ret
  679.     move.l    #1,d0            ;set ret val for finished
  680. ret
  681.     move.l    d3,_rand_val    ;save new random value
  682.     movem.l    (a7)+,regs
  683. #endasm
  684.  
  685. }
  686.  
  687. /*---------------------------------------------------------------------------
  688.  * bitwidth() -- get the # of bits in a long number
  689.  *-------------------------------------------------------------------------*/
  690. bitwidth( n )
  691. register unsigned long n;
  692. {
  693.     register int w;
  694.  
  695.     w = 0;
  696.  
  697.     while( n )
  698.     {
  699.         w++;
  700.         n >>= 1;
  701.     }
  702.     return w;
  703. }
  704.  
  705. /*---------------------------------------------------------------------------
  706.  *
  707.  *-------------------------------------------------------------------------*/
  708.